package com.bdcom.autotest.interaction.http;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CountDownLatch;

import com.bdcom.autotest.telnet.invoke.impl.*;
import com.bdcom.autotest.telnet.model.*;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.bdcom.autotest.MainFrame;
import com.bdcom.autotest.interaction.bean.DeviceUpdBean;
import com.bdcom.autotest.util.Prop;
import org.springframework.util.StringUtils;

public class OperDevice {
	
	private static Logger log = LoggerFactory.getLogger(OperDevice.class);
	
	/**
	 *  单台设备进入monitor 
	 * @param bean
	 * @param call
	 */
	public static void enterMonitor( DeviceUpdBean bean , IEnterMonitorCallback  call ) {
		
		
		Thread t = new Thread() {
			@Override
			public void run() {
				try {
					log.info( "开始进入monitor.....  csport :  " + bean.getConsoleSeverPort() );
					Result result = enterMonitorAndSetMac(bean);
					
					log.info( "进入monitor成功.....  csport :  " + bean.getConsoleSeverPort() );
					bean.setMonitorFlag(true);
					bean.setMonitorStr(result.getRetMsg());
				} catch (Exception e) {
					bean.setMonitorFlag(false);
					bean.setMonitorStr( e.getMessage()  );
					log.info( "进入monitor失败.....  csport :  " + bean.getConsoleSeverPort() );
					log.error( "" , e );
				}

				if (call != null) {
					call.enterMonitorCall(bean);
				}
			}
		};
		t.start();
	}
	
	
	private static Result enterMonitorAndSetMac( DeviceUpdBean bean ) throws Exception {
		String user = "admin";
		String pass = "admin";
		int consoleSeverPort = bean.getConsoleSeverPort();
		Result result = null;
		//formatReboot
		TelnetCMDObj obj = new TelnetCMDObj();
		obj.setIp( Prop.console_server_ip );
		obj.setPort(  consoleSeverPort );
		obj.setUser(user);
		obj.setPassword(pass);
		DevMonitor monitor = new DevMonitor();
		result = monitor.switchMonitor(obj);

		if (!result.getStatus()) {
			throw new Exception("Format reboot失败:" +  result.getFailedReason() );
		}
		//set mac
		DevMACObj obj2 =new DevMACObj();
		obj2.setIp( Prop.console_server_ip );
		obj2.setPort( consoleSeverPort );
		obj2.setUser( user );
		obj2.setPassword(pass);
        //设置MAC
		obj2.setMac( bean.getMac() );
        DevMACSet macSet=new DevMACSet();
        result = macSet.setMAC(obj2);
        if( !result.getStatus()){
        	throw new Exception( "Set mac失败:" + result.getFailedReason() );
        } 
        
        //重启
        TelnetCMDObj obj3 = new TelnetCMDObj();
        //obj.setMonitor(false);//主程序下重启
        obj3.setMonitor(true);//monitor下重启
        obj3.setIp( Prop.console_server_ip );
        obj3.setPort( consoleSeverPort );
        obj3.setUser( user );
        obj3.setPassword( pass );
        DevReboot reboot=new DevReboot();
        result = reboot.reboot(obj3);
        if( !result.getStatus()){
        	throw new Exception(  "Reboot失败:" +result.getFailedReason() );
        } 
        
		return result;  
	}
	
	
	public static void update( List<DeviceUpdBean> beans , IUpdateCallback  call ) {
		

		
		int groupNum = beans.size() ;
		log.info( "当前组内共"+groupNum+"台设备.");
		CountDownLatch counterLatch = new CountDownLatch(groupNum);
		CountDownLatch transferLatch = new CountDownLatch(groupNum);
		Integer syncObj = new Integer(1);
		
		Thread updateMain = new Thread("UpdateMain") {
			@Override
			public void run() {
				
				try {
					for(  int i=0 ; i<groupNum ; i++ ) {
						DeviceUpdBean deviceUpdBean = beans.get(i);
						UpdateThread tt = new UpdateThread( deviceUpdBean  ,counterLatch , transferLatch , syncObj );
						tt.start();
					}
					
					DeviceUpdBean deviceUpdBean = beans.get(0);
					UpdateBaudThread updateBaudThread = new UpdateBaudThread(deviceUpdBean , transferLatch , syncObj) ;
					updateBaudThread.start();
					
					//等待 设备升级完毕 比较完成
					log.info("等待 全部设备 升级 比较完成");
					counterLatch.await();
					
					//恢复波特率
					String oldBaud = deviceUpdBean.getOldBaud();
					String newBaud = deviceUpdBean.getNewBaud();
					try{
						log.info("开始恢复波特率..." );
						if( oldBaud.equals(newBaud)  ) {
							log.info("新旧波特率相同无需恢复： " + newBaud );
						}else {
							if( oldBaud.equals(ConsoleServerOper.baud115200) || oldBaud.equals(ConsoleServerOper.baud9600)  ) {
								int setBaudRate = ConsoleServerOper.setBaudRate(Prop.console_server_ip , oldBaud);
								if( setBaudRate == ConsoleServerOper.SETRES_SUCCESS  ) {
									log.info("波特率成功恢复为： " + oldBaud);
								}else {
									log.error("波特率恢复失败： " +  setBaudRate + " [ SETRES_SETFAIL = 2 ;  SETRES_REBOOTFAIL = 3 ]");
									MainFrame.getInstance().appendLog( "波特率设置失败, 希望重置波特率为"+oldBaud  , true);
								}
							}
						}
					}catch (Exception e){
						MainFrame.getInstance().appendLog( "波特率设置失败, 希望重置波特率为"+oldBaud  , true);
						log.error( "波特率设置失败：" ,e );
					}

				} catch (Exception e) {
					log.error( "" ,e );
				}finally {
					//执行回调 在UI上显示结果
					log.info("执行回调更新UI 结果" );
					if( call != null ) {
						call.updateCall(beans);
					}
				}
				
			}
		};
		updateMain.start();
	}
	
	//针对 某单台设备 重试 升级操作
	public static void update( DeviceUpdBean bean , IUpdateCallback  call ) {
		UpdateThread2 a = new UpdateThread2(bean, call);
		a.start();
	}
	
	
	
	// 设置IP 传文件 reboot
	public static Result setIpAndTransfer(DeviceUpdBean bean, String[] ipmask) throws Exception {
		String user = "admin";
		String pass = "admin";
		if (ipmask == null || ipmask.length != 2) {
			throw new Exception("无法获取可用IP地址下发给设备.");
		}
		if (!bean.getMonitorFlag()) {
			throw new Exception("设备当前不在monitor模式.");
		}

		DevIPObj obj = new DevIPObj();
		obj.setIp(Prop.console_server_ip);
		obj.setPort(bean.getConsoleSeverPort());
		obj.setUser(user);
		obj.setPassword(pass);
		obj.setWantPingIP(Prop.tftp_ip);
		// 设置的ip和mask
		obj.setIpAdd(ipmask[0]);
		obj.setMask(ipmask[1]);
		DevIPSet ipSet = new DevIPSet();
		Result result = ipSet.setIPMask(obj);
		if (!result.getStatus()) {
			log.error( bean.getMac() +"IP地址下发存在问题:"  + result.getFailedReason() + "  ,设备IP 设置为：" +ipmask[0] + "/" +  ipmask[1] );
			throw new Exception( "IP地址下发存在问题." );
		}
		log.info(bean.getMac() + "下发IP地址成功  ，已联通TFTP服务器: " + result.getRetMsg() );
		
		String tftpIp = Prop.tftp_ip;
		
		if ( !StringUtils.isEmpty(bean.getEpromName()) ) {
			Result res = transferEPROMFile(Prop.console_server_ip, bean.getConsoleSeverPort(), user, pass, getFilePath(bean , bean.getEpromName()), tftpIp);
			if (!res.getStatus()) {
				log.error( bean.getMac() +"传输ROM文件失败:"  + res.getFailedReason() );
				throw new Exception("传输ROM文件失败." );
			}
			log.info(bean.getMac() + "传输ROM文件完毕.");
		}
		if ( !StringUtils.isEmpty(bean.getBinName())) {
			Result res = transferFile(Prop.console_server_ip, bean.getConsoleSeverPort(), user, pass, getFilePath(bean , bean.getBinName()), "Switch.bin", tftpIp);
			if (!res.getStatus()) {
				log.error( bean.getMac() +"传输版本文件失败:"  + res.getFailedReason() );
				throw new Exception("传输版本文件失败." );
			}
			log.info(bean.getMac() + "传输版本文件完毕.");
		}
		if ( !StringUtils.isEmpty(bean.getWebName()) ) {
			Result res = transferFile(Prop.console_server_ip, bean.getConsoleSeverPort(), user, pass, getFilePath(bean , bean.getWebName() ), "web.wrp", tftpIp);
			if (!res.getStatus()) {
				log.error( bean.getMac() +"传输WEB文件失败:"  + res.getFailedReason() );
				throw new Exception("传输WEB文件失败." );
			}
			log.info(bean.getMac() + "传输WEB文件完毕.");
		}
		if ( !StringUtils.isEmpty(bean.getLogoName())  ) {
			Result res = transferFile(Prop.console_server_ip, bean.getConsoleSeverPort(), user, pass, getFilePath(bean , bean.getLogoName()), "logo.gif", tftpIp);
			if (!res.getStatus()) {
				log.error( bean.getMac() +"传输LOGO文件失败:"  + res.getFailedReason() );
				throw new Exception("传输LOGO文件失败."  );
			}
			log.info(bean.getMac() + "传输LOGO文件完毕");
		}
		if ( !StringUtils.isEmpty(bean.getConfigName() ) ) {
			Result res = transferConfigFile(Prop.console_server_ip, bean.getConsoleSeverPort(), user, pass, getFilePath(bean , bean.getConfigName()), tftpIp);
			if (!res.getStatus()) {
				log.error( bean.getMac() +"传输Config文件失败:"  + res.getFailedReason() );
				throw new Exception("传输Config文件失败.");
			}
			log.info(bean.getMac() + "传输Config文件完毕");
		}

		TelnetCMDObj rebootObj = new TelnetCMDObj();
		rebootObj.setMonitor(true);// monitor下重启
		rebootObj.setIp(Prop.console_server_ip);
		rebootObj.setPort(bean.getConsoleSeverPort());
		rebootObj.setUser(user);
		rebootObj.setPassword(pass);
		DevReboot reboot = new DevReboot();
		Result result2 = reboot.reboot(rebootObj);
//		if (!result.getStatus()) {
//			throw new Exception("传输文件后重启失败:" + result.getFailedReason());
//		}
		log.info(bean.getMac() +"重启请求已下发.");

		return result;
	}

	private static String getFilePath(DeviceUpdBean bean, String filename) {
		
		String realPath = "/" +bean.getWorkOrderNum()  + "/"+filename;
		return realPath;
		
//		return filename;
	}


	public static Result transferFile(String csip, int csport, String user, String pass, String srcFile, String destFile, String tftpIp) {
		UpgradeMasterObj masterObj = new UpgradeMasterObj();
		masterObj.setIp(csip);
		masterObj.setPort(csport);
		masterObj.setUser(user);
		masterObj.setPassword(pass);
		masterObj.setMonitor(true);
		masterObj.setSrcFile(srcFile);
		masterObj.setDstFile(destFile); // Switch.bin , rom , logo.gif , web.wrp ; default-config
		masterObj.setTftpIP(tftpIp);
		DevUpgradeMaster upgradeMaster = new DevUpgradeMaster();
		Result upgradeResult = upgradeMaster.upgrade(masterObj);
		return upgradeResult;
	}

	public static Result transferEPROMFile(String csip, int csport, String user, String pass, String srcFile, String tftpIp) {
		UpgradeROMObj romObj = new UpgradeROMObj();
		romObj.setIp(csip);
		romObj.setPort(csport);
		romObj.setUser(user);
		romObj.setPassword(pass);
		romObj.setSrcFile(srcFile);
		romObj.setTftpIP(tftpIp);
		DevUpgradeROM upgradeROM = new DevUpgradeROM();
		Result upgradeROMResult = upgradeROM.upgradeROM(romObj);
		return upgradeROMResult;
	}

	public static Result transferConfigFile(String csip, int csport, String user, String pass, String srcFile, String tftpIp) {
		UpgradeDefaultConfigObj defaultConfigObj = new UpgradeDefaultConfigObj();
		defaultConfigObj.setIp(csip);
		defaultConfigObj.setPort(csport);
		defaultConfigObj.setUser(user);
		defaultConfigObj.setPassword(pass);
		defaultConfigObj.setSrcFile(srcFile);
		defaultConfigObj.setTftpIP(tftpIp);
		DevUpgradeDefaultConfig defaultConfig = new DevUpgradeDefaultConfig();
		Result defaultUpgradeResult = defaultConfig.upgrade(defaultConfigObj);
		return defaultUpgradeResult;
	}

	// 比较
	public static boolean compareInfo(DeviceUpdBean bean) {

		TelnetCMDObj obj = new TelnetCMDObj();
		obj.setIp( Prop.console_server_ip );
		obj.setPort( bean.getConsoleSeverPort()  );
		obj.setUser( bean.getUsername() );
		obj.setPassword( bean.getPassword() );
		obj.setMonitor(false);
		DevVerInfo verInfo = new DevVerInfo();
		Result result = verInfo.obtainVerInfo(obj);
		
		if (result.getStatus()) {
			String showVersion = result.getRetMsg();
			String[] split = bean.getBinName().split("_");
			String binVersion1 = split[2];
			String binVersion2 = split[3];
			if(binVersion2.endsWith(".bin")){
				binVersion2=binVersion2.replace(".bin","");
			}
			if( showVersion.indexOf(binVersion1)==-1  ) {
				bean.setResultStr("BIN大版本未成功升级");
				log.error( bean.getMac() +" BIN大版本未成功升级,目的版本["  + binVersion1+"]" +"Current Vession["+showVersion+"]");
				return false;
			}
			if( showVersion.indexOf(binVersion2)==-1  ) {
				bean.setResultStr("BIN小版本未成功升级");
				log.error( bean.getMac() +" BIN小版本未成功升级,目的版本["  + binVersion2+"]" +"Current Vession["+showVersion+"]");
				return false;
			}

			if(null!=bean.getOemsn()&&!bean.getOemsn().equals("")){
				//有eprom sn的比较
				String aa = "Serial num:"+bean.getOemsn();
				if( showVersion.indexOf(aa)==-1  ) {
					bean.setResultStr("OEMSN未成功升级");
					log.error( bean.getMac() +" OEMSN未成功升级,目的OEMSN["  + aa+"]" +"Current Vession["+showVersion+"]");
					return false;
				}
				String aa2 = "ID num:"+bean.getBdsn();
				if( showVersion.indexOf(aa2)==-1  ) {
					bean.setResultStr("BDSN未成功升级");
					log.error( bean.getMac() +" BDSN未成功升级,目的BDSN["  + aa2+"]" +"Current Vession["+showVersion+"]");
					return false;
				}
			}else{
				//没有eprom sn的比较（没有ID num:）
				String aa = "Serial num:"+bean.getBdsn();
				if( showVersion.indexOf(aa)==-1  ) {
					bean.setResultStr("BDSN未成功升级");
					log.error( bean.getMac() +" BDSN未成功升级,目的BDSN["  + aa+"]" +"Current Vession["+showVersion+"]");
					return false;
				}
			}

			if( showVersion.indexOf( bean.getMac() )==-1  ) {
				bean.setResultStr("MAC未成功升级");
				log.error( bean.getMac() +" MAC未成功升级,目的MAC["  + bean.getMac()+"]"+"Current Vession["+showVersion+"]" );
				return false;
			}
		}else {
			bean.setResultStr(bean.getMac()+" 升级后 无法获取 show version 信息.");
			return false;
		} 
		
		return true;
	}
	
	
	
	
	
	
	
	public static void main(String[] args) {
		List<DeviceUpdBean> beans  = new ArrayList<DeviceUpdBean>();
		for(  int i=0; i<5 ;i++  ) {
			DeviceUpdBean b = new DeviceUpdBean();
			beans.add(b);
		}
		update(beans, null);
	}
	
}


class UpdateThread extends Thread{
	
	private static Logger log = LoggerFactory.getLogger(UpdateThread.class);
	
	private DeviceUpdBean  bb;
	private CountDownLatch counterLatch;
	private CountDownLatch transferLatch ;
	private Integer syncObj ;
	
	public UpdateThread( DeviceUpdBean  bb, CountDownLatch counterLatch, CountDownLatch transferLatch, Integer syncObj  ) {
		super();
		this.bb = bb;
		this.counterLatch = counterLatch;
		this.transferLatch = transferLatch;
		this.syncObj= syncObj;
	}
	
	public void run() {
		String[] ipmask = null;
		try {
			boolean flag1 = false;  //记录 设备文件步骤 是否 正常完成
			
			// 设置IP  传文件 reboot
			try {
				log.info( "开始升级...."  + bb.getMac());
				ipmask = NetcardUtil.getIPMASK();
				OperDevice.setIpAndTransfer(bb , ipmask);
				flag1 = true;
				bb.setUdpFlag(true);
			} catch (Exception e) {
				flag1 = false;
				bb.setUdpFlag(false);
				bb.setResultStr(e.getMessage());
			}finally {
				//标记传输完毕
				log.info( bb.getMac() + "升级重启完毕(结果:"+ bb.getUdpFlag() +" , "+ bb.getResultStr()+")，等待修改波特率后进行校验."  );
				transferLatch.countDown();
			}
			
			//等待重启完成以及 波特率修改完成
			synchronized (syncObj) {
				syncObj.wait();
			}
			
			if(  flag1 ) {
				//比较
				boolean compareRes = OperDevice.compareInfo(bb);
				if( compareRes ) {
					bb.setUdpFlag(true);
					bb.setResultStr("升级成功.");
				}else {
					bb.setUdpFlag(false);
					bb.setResultStr( "升级后信息不匹配." + bb.getResultStr() );
				}
			}
			
			log.info( "比较完成."  );

		} catch (Exception e) {
			log.error( "" , e);
		}finally {
			if( ipmask!=null&& ipmask.length == 2 ) {
				NetcardUtil.putIPMASK(ipmask[0], ipmask[1]);
			}
			log.info( bb.getMac() + " 设备执行升级完毕.." + bb.getUdpFlag() + " , " + (bb.getResultStr()==null?"" : bb.getResultStr())  );
			counterLatch.countDown();
		}
		
	}


	
}


class UpdateBaudThread extends Thread{
	
	private static Logger log = LoggerFactory.getLogger(UpdateBaudThread.class);
	
	private DeviceUpdBean  bb;
	private CountDownLatch transferLatch;
	private Integer syncObj ;
	
	public UpdateBaudThread(DeviceUpdBean bb, CountDownLatch transferLatch, Integer syncObj) {
		this.transferLatch =transferLatch;
		this.bb= bb;
		this.syncObj= syncObj;
	}

	public void run() {
		
		String oldBaud = bb.getOldBaud();
		String newBaud = bb.getNewBaud();
		try {
			log.info("等待设备传输文件............");
			transferLatch.await();
			
			// update baud
			log.info("开始修改波特率.....");
			Thread.sleep(1000);//休眠1S  防止  UpdateThread线程 还未还未执行到 wait 方法。
			if( oldBaud.equals(newBaud)  ) {
				log.info("新旧波特率相同 无需修改： " + newBaud );
			}else {
				if( newBaud.equals(ConsoleServerOper.baud115200) || newBaud.equals(ConsoleServerOper.baud9600)  ) {
					int setBaudRate = ConsoleServerOper.setBaudRate(Prop.console_server_ip , newBaud);
					if( setBaudRate == ConsoleServerOper.SETRES_SUCCESS  ) {
						log.info("波特率成功修改为： " + newBaud);
					}else {
						log.error("波特率修改失败： " +  setBaudRate + " [ SETRES_SETFAIL = 2 ;  SETRES_REBOOTFAIL = 3 ]");
						MainFrame.getInstance().appendLog( "波特率设置失败, 希望重置波特率为"+newBaud  , true);
					}
				}
			}
			
		} catch ( Exception e) {
			log.error( "" ,e );
			MainFrame.getInstance().appendLog( "波特率设置失败, 希望重置波特率为"+newBaud  , true);
		}finally {
			//唤醒升级线程开始比较
			synchronized (syncObj) {
				syncObj.notifyAll();	
			}
		}
		
	}
}


/**
 *  针对 某单台设备 重试 升级操作
 * @author GDQ
 *
 */
class UpdateThread2 extends Thread{
	private static Logger log = LoggerFactory.getLogger(UpdateThread2.class);
	
	private DeviceUpdBean  bb;
	IUpdateCallback callback ; 
	
	public UpdateThread2( DeviceUpdBean  bb, IUpdateCallback callback ) {
		super();
		this.callback = callback;
		this.bb=  bb;
	}
	
	@Override
	public void run() {
		
		String[] ipmask = new String[] {};;
		try {
			boolean flag1 = false;  //记录 设备文件步骤 是否 正常完成
			
			
			ipmask = NetcardUtil.getIPMASK();
			OperDevice.setIpAndTransfer(bb, ipmask);
			
			//修改波特率 
			String oldBaud = bb.getOldBaud();
			String newBaud = bb.getNewBaud();
			try {
				if( !oldBaud.equals(newBaud) ) {
					ConsoleServerOper.setBaudRate(Prop.console_server_ip , newBaud);
				}
			} catch (Exception e) {
				log.error( "" ,e ) ;
				MainFrame.getInstance().appendLog( "波特率设置失败, 希望重置波特率为"+newBaud  , true);
				
			}
			// 比较
			boolean compareInfo = OperDevice.compareInfo(bb);
			if(   compareInfo) {
				bb.setUdpFlag(true);
				bb.setResultStr("升级成功.");
			}else {
				bb.setUdpFlag(false);
				bb.setResultStr( "升级后信息不匹配." + bb.getResultStr() );
			}
			
			// 重置波特率
			try {
				if( !oldBaud.equals(newBaud) ) {
					ConsoleServerOper.setBaudRate(Prop.console_server_ip , oldBaud);
				}
			} catch (Exception e) {
				log.error( "" ,e );
				MainFrame.getInstance().appendLog( "波特率设置失败, 希望重置波特率为"+oldBaud  , true);
			}
			
		} catch (Exception e) {
			log.error( "" ,e );
			bb.setUdpFlag(false);
			bb.setResultStr("升级失败:" + e.getMessage());
		}finally {
			if( ipmask!=null&& ipmask.length == 2 ) {
				NetcardUtil.putIPMASK(ipmask[0], ipmask[1]);
			}
			if( callback != null ) {
				callback.updateOneCall(bb);
			}
		}
		
	}
	
}




